package com.ruoyi.point.watcher.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.ruoyi.point.pojo.ConfigurationInformation;
import com.ruoyi.framework.pojo.VirInfo;
import com.ruoyi.point.service.IConfigurationInformationService;
import com.ruoyi.framework.point.PointTable;
import com.ruoyi.framework.watcher.IWatcher;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

@Slf4j
@Component
public class ConfigurationInformationWatcher implements IWatcher {

    @Autowired
    private IConfigurationInformationService configurationInformationService;

    @Autowired
    private PointTable pointTable;

    private static final String NAME_INFO = "ConfigurationInformation";

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().registerModule(new JavaTimeModule());

    @PostConstruct
    public void init() {
        pointTable.addReadWatcher(NAME_INFO,this);
        pointTable.addWriteWatcher(NAME_INFO,this);
    }

    @Override
    @Async
    public List<? extends VirInfo> selectPointInfo(String key,String parameter,Object value) throws RuntimeException {
        String parameters = parameter.replace("$", "");
        if (parameters.equals("all")){
            return configurationInformationService.selectConfigurationInformationList(null);
        } else {
            ConfigurationInformation configurationInformation = new ConfigurationInformation();
            try {
                BeanUtils.setProperty(configurationInformation,parameters,value);
                return configurationInformationService.selectConfigurationInformationList(configurationInformation);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }

    }

    @Override
    @Async
    public void updatePointTableValue(String key, Object value) {
        JsonNode jsonObject = null;
        String[] split = key.split("\\.");
        String id = split[1].replace("$", "");
        try {
            if (id.equals("add")) {
                jsonObject = OBJECT_MAPPER.readTree(value.toString());
                ConfigurationInformation configurationInformation = OBJECT_MAPPER.readValue(jsonObject.traverse(), ConfigurationInformation.class);
                configurationInformationService.insertConfigurationInformation(configurationInformation);
                return;
            }
            String param = split[2];
            ConfigurationInformation configurationInformation = configurationInformationService.selectConfigurationInformationByConfigurationId(Long.valueOf(id));
            if (configurationInformation != null) {
                try {
                    value = value.toString().substring(1, value.toString().length() - 1);
                    BeanUtils.setProperty(configurationInformation,param,value);
                    configurationInformationService.updateConfigurationInformation(configurationInformation);
                    return;
                } catch (IllegalAccessException | InvocationTargetException e) {
                    throw new RuntimeException(e);
                }
            }
        } catch (ArrayIndexOutOfBoundsException | IOException e){
            try {
                jsonObject = OBJECT_MAPPER.readTree(value.toString());
                ConfigurationInformation configurationInformation = OBJECT_MAPPER.readValue(jsonObject.traverse(), ConfigurationInformation.class);
                configurationInformation.setConfigurationId(Long.valueOf(id));
                configurationInformationService.updateConfigurationInformation(configurationInformation);
                return;
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
        throw new NullPointerException("ID does not exist");
    }
}
